<!--
 * @Author: 涵崽
 * @Date: 2023-12-15 14:37:30
 * @email: 1045654@qq.com
 * @gitee: https://gitee.com/han-zai
 * @LastEditors: 涵崽
 * @LastEditTime: 2024-03-01 11:43:02
 * @Description: 微信：1045654

    图片压缩上传
    使用前请先下载插件 npm install --save image-conversion

    action:上传地址,必填项
    size：压缩大小，非必填项，默认500kb
    maxSize:图片最大大小，非必填项，默认1MB
    maxWidth:图片最大宽度，非必填项，默认指定宽度px
-->
<template>
  <div class="select_invoice">
    <el-upload
      class="avatar-uploader"
      :show-file-list="false"
      :action="action"
      :on-success="handleAvatarSuccess"
      :before-upload="beforeUpload"
    >
      <img
        v-if="temporaryImageUrl"
        :src="temporaryImageUrl"
        class="avatar"
      >
      <i
        v-else
        class="el-icon-plus avatar-uploader-icon"
      />
    </el-upload>
  </div>
</template>

<script>
// 引入image-conversion
import * as imageConversion from 'image-conversion'
export default {
  props: {
    imageUrl: {
      type: String,
      default: '' // 图片地址
    },
    action: {
      type: String,
      required: true // 上传地址，必填项
    },
    size: {
      type: Number,
      default: 500 // 指定文件大小
    },
    maxSize: {
      type: Number,
      default: 2 // 指定图片大小，超过此大小则压缩图片
    },
    maxWidth: {
      type: Number,
      default: 200 // 指定宽度
    },
    type: {
      type: String,
      default: 'size' // 指定宽度
    }
  },
  computed: {
    temporaryImageUrl: {
      get() {
        return this.imageUrl
      },
      set(val) {
        this.$emit('update:imageUrl', val) //  改变的时候通知父组件
      }
    }
  },

  created() {
    if (this.type !== 'width' && this.type !== 'size') {
      alert('非法的type值,请检查upload组件的type值是否正确')
    }
  },
  methods: {
    // 第一种,不考虑图片长宽,只考虑图片大小的情况,图片超过？M就压缩
    sizeBeforeUpload(file) {
      return new Promise((resolve, reject) => {
        const isLt2M = file.size / 1024 / 1024 < this.maxSize // 判定图片大小是否小于?MB
        const isImage = file.type.startsWith('image/')
        if (!isImage) {
          this.$message.error('暂不支持除图片以外的文件')
          return
        }
        if (isLt2M) {
          resolve(file)
        }
        // 压缩到指定大小,可自定义
        imageConversion.compressAccurately(file, this.size).then((res) => {
          resolve(res)
        })
      })
    },

    beforeUpload(file) {
      if (this.type === 'size') {
        this.sizeBeforeUpload(file)
      } else if (this.type === 'width') {
        this.widthBeforeUpload(file)
      } else {
        this.$message({
          message: '非法的type值,请检查upload组件的type值是否正确',
          type: 'error'
        })
        return
      }
    },

    // 第二种,图片大小超过4M,宽度超过指定宽度就压缩
    widthBeforeUpload(file) {
      // 图片不大于指定大小,宽度不大于指定宽度
      return new Promise((resolve, reject) => {
        const _URL = window.URL || window.webkitURL
        const isLt2M = file.size / 1024 / 1024 < this.maxSize // 判定图片大小是否小于?MB
        // 这里需要计算出图片的长宽
        const img = new Image()
        img.onload = function() {
          file.width = img.width // 获取到width放在了file属性上
          file.height = img.height // 获取到height放在了file属性上
          const valid = img.width > this.maxWidth // 图片宽度大于指定宽度
          // console.log(11, file)
          // 这里我只判断了图片的宽度,compressAccurately有多个参数时传入对象
          if (valid || isLt2M) {
            imageConversion
              .compressAccurately(file, {
                size: this.size,
                width: this.maxWidth
              })
              .then((res) => {
                resolve(res)
              })
          } else resolve(file)
        }
        // 需要把图片赋值
        img.src = _URL.createObjectURL(file)
      })
    },
    // 上传成功的回调
    handleAvatarSuccess(res, file) {
      console.log(res.data)
      this.temporaryImageUrl = res.data
    }
  }
}
</script>
<style scoped>
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
img {
  width: 100px;
  height: auto;
}
</style>
